/****************************************************************************/
/* File: scs-actions.cpp                                                    */
/* Desc: Implementation file for the input action set type                  */
/* Created: 2014-11-15                                                      */
/* Revised: 2014-11-17                                                      */
/* Authors: Sterling P. de Mille                                            */
/****************************************************************************/

// specification file
#include "scs-actions.h"

SCSactions::SCSactions ()
{
	return;
}

SCSactions::~SCSactions ()
{
	return;
}

void SCSactions::MapInputAction (SCSint32u iInputEvent, SCSaction* pkActionMapping)
{
	SCSint32u iDevice = (iInputEvent & SCS_DEVICE_MASK);
	switch(iDevice) {
	case SCS_DEVICE_KEYBOARD:
		MapKeyboardAction(iInputEvent, pkActionMapping);
		break;
	case SCS_DEVICE_MOUSE:
		MapMouseAction(iInputEvent, pkActionMapping);
		break;
	case SCS_DEVICE_CONTROLLER:
		MapControllerAction(iInputEvent, pkActionMapping);
		break;
	default:
		break;
	}
}

void SCSactions::MapKeyboardAction (SCSint32u iInputEvent, SCSaction* pkActionMapping)
{
	SCSint32u iEvent = (iInputEvent & (~SCS_DEVICE_MASK));
	m_kKeyboardMappings[iEvent] = pkActionMapping;
	m_kActionSet.insert(pkActionMapping);
}

void SCSactions::MapMouseAction (SCSint32u iInputEvent, SCSaction* pkActionMapping)
{
	SCSint32u iEvent = (iInputEvent & (~SCS_DEVICE_MASK));
	m_kMouseMappings[iEvent] = pkActionMapping;
	m_kActionSet.insert(pkActionMapping);
}

void SCSactions::MapControllerAction (SCSint32u iInputEvent, SCSaction* pkActionMapping)
{
	SCSint32u iEvent = (iInputEvent & (~SCS_DEVICE_MASK));
	m_kControllerMappings[iEvent] = pkActionMapping;
	m_kActionSet.insert(pkActionMapping);
}

void SCSactions::Update ()
{
	// update input devices
	UpdateKeyboard();
	UpdateMouse();
	UpdateController();
	// update action set
	UpdateActions();
}

void SCSactions::UpdateActions ()
{
	set<SCSaction*>::iterator iAction;
	for (iAction = m_kActionSet.begin(); iAction != m_kActionSet.end(); iAction++) {
		(*iAction)->Update();
    }
}

void SCSactions::UpdateKeyboard ()
{
	map<SCSint32u,SCSaction*>::iterator iActionMapping;
	for (iActionMapping = m_kKeyboardMappings.begin(); iActionMapping != m_kKeyboardMappings.end(); iActionMapping++) {
		SCSint32u iInputEvent = iActionMapping->first;
		SCSint iKeyCode = (iInputEvent & SCS_KEYCODE_MASK);
		switch(iInputEvent & SCS_INPUT_MASK) {
		case SCS_INPUT_KEY:
			switch(iInputEvent & SCS_ACTION_MASK) {
			case SCS_ACTION_PRESS:
				if (SCSkeyboard::Singleton()->KeyPressed(iKeyCode)) {
					m_kKeyboardMappings[iInputEvent]->Activate();
				} else if (SCSkeyboard::Singleton()->KeyReleased(iKeyCode)) {
					m_kKeyboardMappings[iInputEvent]->Deactivate();
				}
				break;
			case SCS_ACTION_RELEASE:
				if (SCSkeyboard::Singleton()->KeyReleased(iKeyCode)) {
					m_kKeyboardMappings[iInputEvent]->Activate();
				} else if (SCSkeyboard::Singleton()->KeyPressed(iKeyCode)) {
					m_kKeyboardMappings[iInputEvent]->Deactivate();
				}
				break;
			case SCS_ACTION_PRESSED:
				if (SCSkeyboard::Singleton()->KeyDown(iKeyCode)) {
					m_kKeyboardMappings[iInputEvent]->Activate();
				} else if (SCSkeyboard::Singleton()->KeyUp(iKeyCode)) {
					m_kKeyboardMappings[iInputEvent]->Deactivate();
				}
				break;
			case SCS_ACTION_RELEASED:
				if (SCSkeyboard::Singleton()->KeyUp(iKeyCode)) {
					m_kKeyboardMappings[iInputEvent]->Activate();
				} else if (SCSkeyboard::Singleton()->KeyDown(iKeyCode)) {
					m_kKeyboardMappings[iInputEvent]->Deactivate();
				}
				break;
			default:
				break;
			}
			break;
		}
    }
}

void SCSactions::UpdateMouse ()
{
	map<SCSint32u,SCSaction*>::iterator iActionMapping;
	SCSint iDX, iDY;
	SCSint iScrollValue;
	SCSint iButton;

	for (iActionMapping = m_kMouseMappings.begin(); iActionMapping != m_kMouseMappings.end(); iActionMapping++) {
		SCSint32u iInputEvent = iActionMapping->first;
		switch(iInputEvent & SCS_INPUT_MASK) {
		case SCS_INPUT_BUTTON:
			iButton = (iInputEvent & SCS_BUTTON_MASK);
			switch(iInputEvent & SCS_ACTION_MASK) {
			case SCS_ACTION_PRESS:
				if (SCSmouse::Singleton()->ButtonPressed(iButton)) {
					m_kMouseMappings[iInputEvent]->Activate();
				} else if (SCSmouse::Singleton()->ButtonReleased(iButton)) {
					m_kMouseMappings[iInputEvent]->Deactivate();
				}
				break;
			case SCS_ACTION_RELEASE:
				if (SCSmouse::Singleton()->ButtonReleased(iButton)) {
					m_kMouseMappings[iInputEvent]->Activate();
				} else if (SCSmouse::Singleton()->ButtonPressed(iButton)) {
					m_kMouseMappings[iInputEvent]->Deactivate();
				}
				break;
			case SCS_ACTION_PRESSED:
				if (SCSmouse::Singleton()->ButtonDown(iButton)) {
					m_kMouseMappings[iInputEvent]->Activate();
				} else if (SCSmouse::Singleton()->ButtonUp(iButton)) {
					m_kMouseMappings[iInputEvent]->Deactivate();
				}
				break;
			case SCS_ACTION_RELEASED:
				if (SCSmouse::Singleton()->ButtonUp(iButton)) {
					m_kMouseMappings[iInputEvent]->Activate();
				} else if (SCSmouse::Singleton()->ButtonDown(iButton)) {
					m_kMouseMappings[iInputEvent]->Deactivate();
				}
				break;
			}
			break;
		case SCS_INPUT_WHEEL:
			switch(iInputEvent & SCS_ACTION_MASK) {
			case SCS_ACTION_SCROLL:
				switch(iInputEvent & SCS_DIRECTION_MASK) {
				case SCS_DIRECTION_UP:
					iScrollValue = SCSmouse::Singleton()->ScrollValue();
					if (iScrollValue > 0) {
						m_kMouseMappings[iInputEvent]->Activate(iScrollValue);
					} else {
						m_kMouseMappings[iInputEvent]->Deactivate();
					}
					break;
				case SCS_DIRECTION_DOWN:
					iScrollValue = -SCSmouse::Singleton()->ScrollValue();
					if (iScrollValue > 0) {
						m_kMouseMappings[iInputEvent]->Activate(iScrollValue);
					} else {
						m_kMouseMappings[iInputEvent]->Deactivate();
					}
					break;
				}
				break;
			}
			break;
		case SCS_INPUT_AXIS:
			switch(iInputEvent & SCS_ACTION_MASK) {
			case SCS_ACTION_MOVE:
				switch(iInputEvent & SCS_DIRECTION_MASK) {
				case SCS_DIRECTION_UP:
		            iDY = -SCSmouse::Singleton()->DeltaY();
		            if (iDY > 0) {
		            	m_kMouseMappings[iInputEvent]->Activate(iDY);
		            } else {
		            	m_kMouseMappings[iInputEvent]->Deactivate();
		            }
					break;
				case SCS_DIRECTION_DOWN:
		            iDY = SCSmouse::Singleton()->DeltaY();
		            if (iDY > 0) {
		            	m_kMouseMappings[iInputEvent]->Activate(iDY);
		            } else {
		            	m_kMouseMappings[iInputEvent]->Deactivate();
		            }
					break;
				case SCS_DIRECTION_LEFT:
		            iDX = -SCSmouse::Singleton()->DeltaX();
		            if (iDX > 0) {
		            	m_kMouseMappings[iInputEvent]->Activate(iDX);
		            } else {
		            	m_kMouseMappings[iInputEvent]->Deactivate();
		            }
					break;
				case SCS_DIRECTION_RIGHT:
		            iDX = SCSmouse::Singleton()->DeltaX();
		            if (iDX > 0) {
		            	m_kMouseMappings[iInputEvent]->Activate(iDX);
		            } else {
		            	m_kMouseMappings[iInputEvent]->Deactivate();
		            }
					break;
				}
				break;
			}
			break;
		}
    }
}

void SCSactions::UpdateController ()
{
	map<SCSint32u,SCSaction*>::iterator iActionMapping;
	SCSint32u iInputEvent;
	SCSint32u iButton;
	SCSint32u iAction;
	SCSint32u iInput;
	SCSint32u iDirection;
	SCSint32u iDpad;
	SCSint32u iAxis;
	SCSint iDY;
	SCSint iDX;

	for (iActionMapping = m_kControllerMappings.begin(); iActionMapping != m_kControllerMappings.end(); iActionMapping++) {
		iInputEvent = iActionMapping->first;
		iAction = (iInputEvent & SCS_ACTION_MASK);
		iInput = (iInputEvent & SCS_INPUT_MASK);
		iButton = (iInputEvent & SCS_BUTTON_MASK);
		iDirection = (iInputEvent & SCS_DIRECTION_MASK);
		iAxis = (iInputEvent & SCS_AXIS_MASK);
		iDpad = (iInputEvent & SCS_DPAD_MASK);

		switch (iInput) {
		case SCS_INPUT_BUTTON:
			switch(iAction) {
			case SCS_ACTION_PRESS:
				if (SCScontroller::Singleton()->ButtonPress(iButton)) {
					m_kControllerMappings[iInputEvent]->Activate();
				} else if (SCScontroller::Singleton()->ButtonRelease(iButton)) {
					m_kControllerMappings[iInputEvent]->Deactivate();
				}
				break;
			case SCS_ACTION_RELEASE:
				if (SCScontroller::Singleton()->ButtonRelease(iButton)) {
					m_kControllerMappings[iInputEvent]->Activate();
				} else if (SCScontroller::Singleton()->ButtonPress(iButton)) {
					m_kControllerMappings[iInputEvent]->Deactivate();
				}
				break;
			case SCS_ACTION_PRESSED:
				if (SCScontroller::Singleton()->ButtonPressed(iButton)) {
					m_kControllerMappings[iInputEvent]->Activate();
				} else if (SCScontroller::Singleton()->ButtonReleased(iButton)) {
					m_kControllerMappings[iInputEvent]->Deactivate();
				}
				break;
			case SCS_ACTION_RELEASED:
				if (SCScontroller::Singleton()->ButtonReleased(iButton)) {
					m_kControllerMappings[iInputEvent]->Activate();
				} else if (SCScontroller::Singleton()->ButtonPressed(iButton)) {
					m_kControllerMappings[iInputEvent]->Deactivate();
				}
				break;
			}
			break;
		case SCS_INPUT_AXIS:
			switch(iAction) {
			case SCS_ACTION_PRESS:
				switch(iAxis) {
				case SCScontroller::AXIS_THUMBSTICK_LEFT_Y:
				case SCScontroller::AXIS_THUMBSTICK_RIGHT_Y:
				case SCScontroller::AXIS_THUMBSTICK_LEFT_X:
				case SCScontroller::AXIS_THUMBSTICK_RIGHT_X:
					switch(iInputEvent & SCS_DIRECTION_MASK) {
					case SCS_DIRECTION_UP:
					case SCS_DIRECTION_LEFT:
						if (SCScontroller::Singleton()->AxisPress(iAxis) < 0) {
							m_kControllerMappings[iInputEvent]->Activate();
						} else if (SCScontroller::Singleton()->AxisRelease(iAxis)) {
							m_kControllerMappings[iInputEvent]->Deactivate();
						} else if (SCScontroller::Singleton()->AxisPress(iAxis) > 0) {
							m_kControllerMappings[iInputEvent]->Deactivate();
						}
						break;
					case SCS_DIRECTION_DOWN:
					case SCS_DIRECTION_RIGHT:
						if (SCScontroller::Singleton()->AxisPress(iAxis) > 0) {
							m_kControllerMappings[iInputEvent]->Activate();
						} else if (SCScontroller::Singleton()->AxisRelease(iAxis)) {
							m_kControllerMappings[iInputEvent]->Deactivate();
						} else if (SCScontroller::Singleton()->AxisPress(iAxis) < 0) {
							m_kControllerMappings[iInputEvent]->Deactivate();
						}
						break;
					}
					break;
				}
				break;
			case SCS_ACTION_RELEASE:
				switch(iAxis) {
				case SCScontroller::AXIS_THUMBSTICK_LEFT_Y:
				case SCScontroller::AXIS_THUMBSTICK_RIGHT_Y:
				case SCScontroller::AXIS_THUMBSTICK_LEFT_X:
				case SCScontroller::AXIS_THUMBSTICK_RIGHT_X:
					switch(iInputEvent & SCS_DIRECTION_MASK) {
					case SCS_DIRECTION_UP:
					case SCS_DIRECTION_LEFT:
					case SCS_DIRECTION_DOWN:
					case SCS_DIRECTION_RIGHT:
						if (SCScontroller::Singleton()->AxisRelease(iAxis)) {
							m_kControllerMappings[iInputEvent]->Activate();
						} else if (SCScontroller::Singleton()->AxisPress(iAxis) > 0) {
							m_kControllerMappings[iInputEvent]->Deactivate();
						} else if (SCScontroller::Singleton()->AxisPress(iAxis) < 0) {
							m_kControllerMappings[iInputEvent]->Deactivate();
						}
						break;
					}
					break;
				}
				break;
			case SCS_ACTION_PRESSED:
				switch(iAxis) {
				case SCScontroller::AXIS_THUMBSTICK_LEFT_Y:
				case SCScontroller::AXIS_THUMBSTICK_RIGHT_Y:
				case SCScontroller::AXIS_THUMBSTICK_LEFT_X:
				case SCScontroller::AXIS_THUMBSTICK_RIGHT_X:
					switch(iInputEvent & SCS_DIRECTION_MASK) {
					case SCS_DIRECTION_UP:
					case SCS_DIRECTION_LEFT:
						if (SCScontroller::Singleton()->AxisPressed(iAxis) < 0) {
							m_kControllerMappings[iInputEvent]->Activate();
						} else if (SCScontroller::Singleton()->AxisReleased(iAxis)) {
							m_kControllerMappings[iInputEvent]->Deactivate();
						} else if (SCScontroller::Singleton()->AxisPressed(iAxis) > 0) {
							m_kControllerMappings[iInputEvent]->Deactivate();
						}
						break;
					case SCS_DIRECTION_DOWN:
					case SCS_DIRECTION_RIGHT:
						if (SCScontroller::Singleton()->AxisPressed(iAxis) > 0) {
							m_kControllerMappings[iInputEvent]->Activate();
						} else if (SCScontroller::Singleton()->AxisReleased(iAxis)) {
							m_kControllerMappings[iInputEvent]->Deactivate();
						} else if (SCScontroller::Singleton()->AxisPressed(iAxis) < 0) {
							m_kControllerMappings[iInputEvent]->Deactivate();
						}
						break;
					}
					break;
				}
				break;
			case SCS_ACTION_RELEASED:
				switch(iAxis) {
				case SCScontroller::AXIS_THUMBSTICK_LEFT_Y:
				case SCScontroller::AXIS_THUMBSTICK_RIGHT_Y:
				case SCScontroller::AXIS_THUMBSTICK_LEFT_X:
				case SCScontroller::AXIS_THUMBSTICK_RIGHT_X:
					switch(iInputEvent & SCS_DIRECTION_MASK) {
					case SCS_DIRECTION_UP:
					case SCS_DIRECTION_LEFT:
					case SCS_DIRECTION_DOWN:
					case SCS_DIRECTION_RIGHT:
						if (SCScontroller::Singleton()->AxisReleased(iAxis)) {
							m_kControllerMappings[iInputEvent]->Activate();
						} else if (SCScontroller::Singleton()->AxisPressed(iAxis) > 0) {
							m_kControllerMappings[iInputEvent]->Deactivate();
						} else if (SCScontroller::Singleton()->AxisPressed(iAxis) < 0) {
							m_kControllerMappings[iInputEvent]->Deactivate();
						}
						break;
					}
					break;
				}
				break;
			case SCS_ACTION_MOVE:
				switch(iDirection) {
				case SCS_DIRECTION_UP:
		            iDY = -SCScontroller::Singleton()->AxisMotion(iAxis);
					if (iDY > 0) {
						m_kControllerMappings[iInputEvent]->Activate(iDY);
					} else {
						m_kControllerMappings[iInputEvent]->Deactivate();
					}
					break;
				case SCS_DIRECTION_DOWN:
		            iDY = SCScontroller::Singleton()->AxisMotion(iAxis);
					if (iDY > 0) {
						m_kControllerMappings[iInputEvent]->Activate(iDY);
					} else {
						m_kControllerMappings[iInputEvent]->Deactivate();
					}
					break;
				case SCS_DIRECTION_LEFT:
		            iDX = -SCScontroller::Singleton()->AxisMotion(iAxis);
					if (iDX > 0) {
						m_kControllerMappings[iInputEvent]->Activate(iDX);
					} else {
						m_kControllerMappings[iInputEvent]->Deactivate();
					}
					break;
				case SCS_DIRECTION_RIGHT:
		            iDX = SCScontroller::Singleton()->AxisMotion(iAxis);
					if (iDX > 0) {
						m_kControllerMappings[iInputEvent]->Activate(iDX);
					} else {
						m_kControllerMappings[iInputEvent]->Deactivate();
					}
					break;
				}
				break;
			}
			break;
		case SCS_INPUT_DPAD:
			switch(iAction) {
			case SCS_ACTION_PRESS:
				if (SCScontroller::Singleton()->DpadPress(iDpad)) {
					m_kControllerMappings[iInputEvent]->Activate();
				} else if (SCScontroller::Singleton()->DpadRelease(iDpad)) {
					m_kControllerMappings[iInputEvent]->Deactivate();
				}
				break;
			}
			break;
		}
	}
}
